/* This file is part of Open Source Project, KrishiSuvidha
 * (C) 2010 , Ambuj Varshney
 * This is released according to GPL V3
 * Krishi Menu is a class for displaying menu, icons and playing sound of the 
 * chosen menu item.
 */


import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Canvas;
import java.io.IOException;
import java.io.InputStream;
import java.lang.String;
import javax.microedition.midlet.*;
import javax.microedition.media.*;
 
public class KrishiMenu extends Canvas{

		private Display dis; // This holds the passed reference to displayable object
		private String[] Menu_Items;
		private String[] AudioF;
		private String[] IconsF;
		private int Screen_no; // This variable holds the current screen number of Menu Items
		private int x_screen; // This is the maximum possible X-Coordinate that Mobile Screen supports
		private int y_screen; // This is the maximum possible y-coordinate mobile screen supports
		private int no_screen; // this holds the number of screens possible
		private int items_per_screen = 5; // This is the number of items per screen we want
		private final int iconsz_x = 50;
		private final int iconsz_y = 80;
		private buttons[] button_list; // This is the buttons on our KrishiMenu
		private int menu_item_size;
		private int pres_selected_item;
		private int no_of_items; // This is the number of menuitems presently
		private int MaxScreen; // This holds the maximum number of possible screens
		// Constructor uses XML file as an argument and parses the XML file to find the 
		// Relevant menu details.
		private int item_last_page;
		
		
		/* This is the constructor that would be called incase we are passing
	    XML file as argument. XML file is parsed, relevant details parsed and included
	    in KrishiMenu module. */
		
		public KrishiMenu( String XML_file , int x , int y)
		{
			
			x_screen = x;
			y_screen = y;
			
		}
		
		/* This constructor takes three String array as argument and initialises internal
	    Data structures with the passed value */
		
		public KrishiMenu(String []M1, String []A1 , String []I1 , int x, int y)
		{
			setFullScreenMode(true);
			
			Menu_Items = M1;
			AudioF = I1;
			IconsF = A1;
			x_screen = x;
			y_screen = y;
			
			// We assume here that no of Items per screen would be ITEMS_PER_SCREEN
			
			if(M1.length >= items_per_screen)
				no_screen = M1.length / items_per_screen;
		
			// Find the Screen Height and Width of Mobile phone
			x_screen = getWidth();
			y_screen = getHeight();
			
			// First Screen has Screen Number 0
			Screen_no = 0;
			
			// Find Menu Item size based on the number of items per screen
			menu_item_size = y_screen / (items_per_screen + 1);
			
			// Maximum number of screens possible
			MaxScreen =  (int) java.lang.Math.ceil((double)((double)M1.length / (double)items_per_screen));
			 
			/* Find number of items in the last page of our screen module
		    If number of passed items is perfectly divisble by items_per_screen
		    Number of menu items in last page is items_per_screen otherwise its a modulo
			of number of items in last page */
			
			if( ( M1.length % items_per_screen) == 0 )
				item_last_page = items_per_screen;
			else
				item_last_page = M1.length % items_per_screen;
	
		}
		
		public void setScreenSz(int x, int y)
		{
			x_screen = x;
			y_screen = y;
		}
		
		public void setDisplayable(Display d)
		{
			dis = d;
		}
		
		/* Function Initialises the Button_List array and different parameters used during the
	    program. This function has to be called before any other function, otherwise exception
	    Could be thrown. Different attributes for example its position on screen is also set during
	    Execution of this function. */
		
		void initialize_buttons()
		{
			button_list = new buttons[Menu_Items.length];
			int i;
			int y=0;
			no_of_items = 0;
			
			for(i = 0 ; i < Menu_Items.length ; i++)
			{
				
				if( (y_screen - (y + menu_item_size)) >= menu_item_size) 
				{
					button_list[i] = new buttons(Menu_Items[i] , IconsF[i], 0 , y  );
					button_list[i].setScreenSize(getWidth(), getHeight());
					button_list[i].setMenuSize(menu_item_size);
					button_list[i].setAudio(AudioF[i]);
					no_of_items++;
					y = y + menu_item_size;
				}
				else
				{
					y = 0;
					System.out.println("entered alternate loop for i = " + i);
					button_list[i] = new buttons(Menu_Items[i] , IconsF[i], 0 , y );
					button_list[i].setScreenSize(getWidth(), getHeight());
					button_list[i].setMenuSize(menu_item_size);
					button_list[i].setAudio(AudioF[i]);
					no_of_items++;
					y = y + menu_item_size;
				}
				
			}
		
			// Chose the first added button and toggle its state to selected.
			button_list[0].toggleState();
		 	pres_selected_item = 0;
	 		
		}
		
		
		// We look for various user Inputs in this module and based on the input we give appropriate 
		// Response
	
		protected void keyPressed(int keycode)
		{
			if(keycode == KEY_NUM5)
			{
				String test = " This is a test string! :) ";
				try {
					Image img = Image.createImage("/OpeningScreen.png");
					InformationDisplay d1 = new InformationDisplay(test,img,dis,this );
					
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				
			}
			
			if(keycode == KEY_NUM6)
			{
				System.out.println("PRESSED!");
				if( (Screen_no+1) < MaxScreen)
				{
					Screen_no ++;
					
					button_list[pres_selected_item].toggleState();
					pres_selected_item = ( Screen_no )* items_per_screen;
					button_list[pres_selected_item].toggleState();
					
				}
				this.repaint();
			}
			
			if( keycode == KEY_NUM4)
			{
				if( Screen_no > 0)
				{
					
					Screen_no -- ;
					button_list[pres_selected_item].toggleState();
					pres_selected_item = (Screen_no * items_per_screen);
					button_list[pres_selected_item].toggleState();
					
				}
				
				this.repaint();
				
			}
			if(keycode == KEY_NUM8 || keycode == DOWN)
			{
				button_list[pres_selected_item].toggleState();
				
				if(!( (( (pres_selected_item+1) % (items_per_screen) ) == 0) && (pres_selected_item != 0 )))
					pres_selected_item++;
		
				 if( (pres_selected_item >= no_of_items))
					pres_selected_item = (Screen_no)* items_per_screen;
				
				button_list[pres_selected_item].toggleState();
				this.repaint();
				
			}
			
			if(keycode == KEY_NUM2 || keycode == UP)
			{
				button_list[pres_selected_item].toggleState();
				pres_selected_item--;
			  
				// If initally pres_selected_item was 0 and we press the up button again
				// we enter the loop below which means that we go remain at the previous state.
				
				if(pres_selected_item < (Screen_no * items_per_screen) )
					pres_selected_item = (Screen_no * items_per_screen);
				
				button_list[pres_selected_item].toggleState();
				
				this.repaint();
			}

		
		}
		
		
		public void paint(Graphics g)
		{ 
			int i;
			int lower_limit;
			int upper_limit;
			
			g.setColor(255,255,255);
			g.fillRect(0,0,getWidth(), getHeight());
			
			if( (Screen_no+1) == MaxScreen)
			{
			 	lower_limit = Screen_no;
				lower_limit = (lower_limit * items_per_screen);
				upper_limit = ( lower_limit + item_last_page)-1;
			 	
			}
			else
			{
			 	lower_limit = Screen_no;
				lower_limit = lower_limit * items_per_screen;
				upper_limit = lower_limit + items_per_screen - 1;
			 
			}
			 
			for(i = lower_limit; i <= upper_limit ; i++)
				button_list[i].draw(g);
		 
 	 	}
		
		public void repaint(Graphics g)
		{
			int i;
			int lower_limit;
			int upper_limit;
			
			g.setColor(255,255,255);
			g.fillRect(0,0,getWidth(), getHeight());
			
			if( (Screen_no+1) == MaxScreen)
			{
		 		lower_limit = Screen_no;
				lower_limit = (lower_limit * items_per_screen);
				upper_limit = ( lower_limit + item_last_page)-1;
			 	
			}
			else
			{
		 		lower_limit = Screen_no;
				lower_limit = lower_limit * items_per_screen;
				upper_limit = lower_limit + items_per_screen -1;
			 
			}
			for(i = lower_limit; i <= upper_limit ; i++)
				button_list[i].draw(g);
		}
		 
		
		/* This is an Internal class used for representing buttons used in our Graphical Menu
		 * In addition to including the image and text for the button, the class can also include
		 * the audio associated with the button and whenever the state of the button chanegs and is
		 * toggled active the associated audio is played back.
		 */
		
		private class buttons {
			
			// Buttons attribute
			private String text;
			private String IconN;
			private String audio_file; // This holds the name of the audio file associated with this button
			private int x;
			private int y;
			private int sc_siz_x;
			private int sc_siz_y;
			private int menu_item_size;
			
			// Flag whether audio is associated with this button
			boolean has_audio = false;
		
			boolean state; // Is true if the button is selected , false otherwise
		 
			// These are constants that define the color used in the buttons.
			private final int BG_COLOR_SELECTED = 0x0000FF;
			private final int BG_COLOR_NOTSELECTED = 0xFFFFFF;
			private final int textColor = 0x000000;
			
			// These are constants that define the icon dimensions used in the buttons.
			private final int iconsz_x = 200;
			private final int iconsz_y = 80;
			
			
			buttons(String txt, String icn ,int x1, int y1)
			{
				
				text = txt;
				IconN = icn; 
				x = x1;
				y = y1;
				state = false;
			 
				
			}
			
			// Associates audio file with the button and toggles has_audio flag
			
			public void setAudio(String aud)
			{
				audio_file = aud;
				has_audio  = true;
			}
			
			public void setScreenSize(int x1, int y1)
			{
				sc_siz_x = x1;
				sc_siz_y = y1;
			}
			
			public void setMenuSize(int y)
			{
				menu_item_size = y;
			}
			
			public void toggleState()
			{
				if(state)
					state = false;
				else
				{
					state = true;
					
					// We check whether any audio file is associated with this button
					// and if any Audio file is associated with this button we playback the associated 
					// Audio file
					
					if(has_audio)
					{
					try{
						
						System.out.println("Playing Audio File " + audio_file);
						
						// Create an Input Stream of the Passed audio_file and Pass it to Manager to start control
						// and playing of the audio file
						
						InputStream in = getClass().getResourceAsStream(audio_file);
						Player p =  Manager.createPlayer(in,"audio/amr");
					 	p.realize();
						p.prefetch();
						p.start(); // Start playing the audio file
						
						
					} catch (MediaException pe)
					{
					
						System.out.println("Button class throws MediaException!");
					
					} catch (IOException e) {
					 
						System.out.println(" Button Class throws IOException");
						e.printStackTrace();
					
					}
					
					}
				}
			}
			
			// We draw the button here :)
			
			public void draw(Graphics g1)
			{
				
				if( state == true)
					g1.setColor(BG_COLOR_SELECTED);
				else
					g1.setColor(BG_COLOR_NOTSELECTED);
				
				g1.fillRect(x+1,y+1, sc_siz_x ,menu_item_size);
				 
				g1.setColor(255,0,0);
		 		g1.drawString( text , x + iconsz_x , y , g1.RIGHT | g1.TOP );
		 		Image img;
				try {
			
					img = Image.createImage(IconN);
					g1.drawImage(img,x , y, g1.LEFT | g1.TOP );
				
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		 	
			}

	}
		 
}
